﻿using System;
using System.Diagnostics;

namespace PlayTrace
{
    sealed class TestListeners
    {
        private static void CheckWriteFile(Action actPreTrace, Action actPostTrace)
        {
            Trace.Listeners.Clear();
            Trace.Listeners.Add(new ConsoleTraceListener());
            Trace.Listeners.Add(new TextWriterTraceListener("TestWriterListeners.log"));

            actPreTrace();

            Trace.TraceInformation("inforamtion");
            Trace.TraceWarning("warning");
            Trace.TraceError("error");

            actPostTrace();
        }

        /// <summary>
        /// chekanote: from this test, we can see if no flush (auto or manual), the messages won't be dumped into file
        /// </summary>
        private static void TestWriteFile_NoFlushNoOutput()
        {
            CheckWriteFile(
                () => Trace.WriteLine("*********** AutoFlush Not Set.\n"),
                () => Trace.WriteLine("\n*********** Flush Not Invoked.\n"));
        }

        /// <summary>
        /// chekanote: set "Trace.AutoFlush" can automatically flush after every writing
        /// but it seems that you cannot use "\n" in the messages
        /// those "\n" can be correctly intepreted in Console
        /// but in file, "\n" intepreted as "^M", which cause some difficulty when opened with NotePad
        /// but Vim can correctly deal with "^M"
        /// chekanote: and files are always opened in a "append" mode
        /// </summary>
        private static void TestWriteFile_AutoFlush()
        {
            CheckWriteFile(
                () => Trace.AutoFlush = true,
                () => Trace.WriteLine("\n############### TestWithAutoFlush done.\n"));
        }

        /// <summary>
        /// chekanote: same feature as "AutoFlush=true", and also some problems with "\n"
        /// </summary>
        private static void TestWriteFile_ManualFlush()
        {
            CheckWriteFile(
                () => { },
                () =>
                {
                    Trace.WriteLine("\n!!!!!!!!!!!!!!!!! About to call Flush().");
                    Trace.Flush();
                });
        }

        private static void TestListenersInConfigFile()
        {
            TraceListener listener = Trace.Listeners["myConsoleListener"];
            listener.TraceOutputOptions = TraceOptions.Timestamp | TraceOptions.ThreadId;

            Trace.TraceInformation("information");
            Trace.TraceWarning("warning");
            Trace.TraceError("error");

            // chekanote: since DefaultListener is removed, so below "Fail" will NOT pop MessageBox to remind
            Trace.Fail("!!!!!!!!!!!!!!!!!! trace - failed");
            Debug.Fail("!!!!!!!!!!!!!!!!!! debug - failed");

            Trace.Flush();
        }

        private static void CheckCustomListener(TraceListener listener, Action<TraceListener> actPostTrace)
        {
            Trace.Listeners.Clear();
            Trace.Listeners.Add(listener);

            Trace.TraceInformation("information");
            Trace.TraceWarning("warning");
            Trace.TraceError("error");
            Trace.Fail("failure");

            actPostTrace(listener);
        }

        /// <summary>
        /// from this demo, we can see that, for each message, TraceListener will be invoked twice
        /// 1. TraceListener.Write will be invoked to print the header. the header includes: Source + EventType + EventId
        /// 2. TraceListener.WriteLine will be invoked to print the message itself
        /// </summary>
        private static void TestHowTraceListenerWorks()
        {
            CheckCustomListener(
                new RecordListener(),
                listener =>
                {
                    RecordListener recorder = listener as RecordListener;

                    int index = 0;
                    foreach (string message in recorder.Messages)
                    {
                        ++index;
                        Console.WriteLine("{0,-2}.\t{1}", index, message);
                    }
                });
        }

        public static void TestMain()
        {
            // TestWriteFile_NoFlushNoOutput();
            // TestWriteFile_AutoFlush();
            // TestWriteFile_ManualFlush();
            // TestListenersInConfigFile();
            // CheckCustomListener(new OnlyMsgConsoleListener("hello"),listener=> { });
            TestHowTraceListenerWorks();
        }
    }
}
